//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package org_eval_dao

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/dao/db_ns"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_evaluate_api"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type EvaluateInfoDbItem struct {
	EvaluateId       string   `bson:"_id"`
	OrgId            string   `bson:"orgId"`
	DepartMentId     string   `bson:"departMentId"`
	EvaluateTitle    string   `bson:"evaluateTitle"`
	EvaluateDesc     string   `bson:"evaluateDesc"`
	MemberUserIdList []string `bson:"memberUserIdList"`
	TargetIdList     []string `bson:"targetIdList"`
	EvaluateState    uint32   `bson:"evaluateState"`
	CreateUserId     string   `bson:"createUserId"`
	CreateTime       int64    `bson:"createTime"`
	UpdateUserId     string   `bson:"updateUserId"`
	UpdateTime       int64    `bson:"updateTime"`
}

func (item *EvaluateInfoDbItem) ToEvaluateInfo() *org_evaluate_api.EvaluateInfo {
	memberList := []*org_evaluate_api.EvaluateMemberInfo{}
	for _, memberUserId := range item.MemberUserIdList {
		memberInfo := &org_evaluate_api.EvaluateMemberInfo{
			MemberUserId: memberUserId,
			ScoreList:    []*org_evaluate_api.EvaluateTargetScore{},
			HasEvaluate:  false,
		}
		for _, targetId := range item.TargetIdList {
			memberInfo.ScoreList = append(memberInfo.ScoreList, &org_evaluate_api.EvaluateTargetScore{
				TargetId: targetId,
			})
		}
		memberList = append(memberList, memberInfo)
	}
	return &org_evaluate_api.EvaluateInfo{
		EvaluateId:    item.EvaluateId,
		EvaluateTitle: item.EvaluateTitle,
		EvaluateDesc:  item.EvaluateDesc,
		MemberList:    memberList,
		EvaluateState: org_evaluate_api.EVALUATE_STATE(item.EvaluateState),
		DepartMentId:  item.DepartMentId,
		CreateUserId:  item.CreateUserId,
		CreateTime:    item.CreateTime,
		UpdateUserId:  item.UpdateUserId,
		UpdateTime:    item.UpdateTime,
		UserPerm: &org_evaluate_api.UserPerm{
			CanUpdate: false,
			CanRemove: false,
		},
	}
}

type _EvaluateDao struct {
	mc *mongo.Collection
}

func newEvaluateDao(db *mongo.Database) (*_EvaluateDao, error) {
	mc := db.Collection(db_ns.DB_NS_ORG_EVAL + "evaluate")
	_, err := mc.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
		{
			Keys: bson.D{{"orgId", 1}, {"departMentId", 1}, {"memberUserIdList", 1}, {"createTime", 1}},
		},
		{
			Keys: bson.D{{"orgId", 1}, {"targetIdList", 1}},
		},
	})
	if err != nil {
		return nil, err
	}
	return &_EvaluateDao{mc: mc}, nil
}

func (db *_EvaluateDao) Insert(ctx context.Context, dbItem *EvaluateInfoDbItem) error {
	_, err := db.mc.InsertOne(ctx, dbItem)
	return err
}

func (db *_EvaluateDao) Exist(ctx context.Context, orgId, evaluateId string) (bool, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"_id": evaluateId, "orgId": orgId})
	return count > 0, err
}

func (db *_EvaluateDao) Get(ctx context.Context, orgId, evaluateId string) (*EvaluateInfoDbItem, error) {
	retItem := &EvaluateInfoDbItem{}
	err := db.mc.FindOne(ctx, bson.M{"_id": evaluateId, "orgId": orgId}).Decode(retItem)
	return retItem, err
}

func (db *_EvaluateDao) Remove(ctx context.Context, orgId, evaluateId string) error {
	_, err := db.mc.DeleteOne(ctx, bson.M{"_id": evaluateId, "orgId": orgId})
	return err
}

func (db *_EvaluateDao) RemoveByOrg(ctx context.Context, orgId string) error {
	_, err := db.mc.DeleteMany(ctx, bson.M{"orgId": orgId})
	return err
}

func (db *_EvaluateDao) Count(ctx context.Context, orgId, departMentId string, filterByMemberUserId bool, memberUserId string) (uint32, error) {
	query := bson.M{"orgId": orgId, "departMentId": departMentId}
	if filterByMemberUserId {
		query["memberUserIdList"] = memberUserId
	}
	count, err := db.mc.CountDocuments(ctx, query)
	return uint32(count), err
}

func (db *_EvaluateDao) List(ctx context.Context, orgId, departMentId string, filterByMemberUserId bool, memberUserId string, offset, limit int64) ([]*EvaluateInfoDbItem, error) {
	query := bson.M{"orgId": orgId, "departMentId": departMentId}
	if filterByMemberUserId {
		query["memberUserIdList"] = memberUserId
	}
	cursor, err := db.mc.Find(ctx, query, options.Find().SetSkip(offset).SetLimit(limit).SetSort(bson.M{"createTime": -1}))
	if err != nil {
		return nil, err
	}
	retList := []*EvaluateInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}

func (db *_EvaluateDao) CountByTarget(ctx context.Context, orgId, targetId string) (uint32, error) {
	query := bson.M{"orgId": orgId, "targetIdList": targetId}
	count, err := db.mc.CountDocuments(ctx, query)
	return uint32(count), err
}

func (db *_EvaluateDao) Update(ctx context.Context, orgId, evaluateId, evaluateTitle, evaluateDesc string, memberUserIdList, targetIdList []string, updateUserId string, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": evaluateId, "orgId": orgId}, bson.M{
		"$set": bson.M{
			"evaluateTitle":    evaluateTitle,
			"evaluateDesc":     evaluateDesc,
			"memberUserIdList": memberUserIdList,
			"targetIdList":     targetIdList,
			"updateUserId":     updateUserId,
			"updateTime":       updateTime,
		},
	})
	return err
}

func (db *_EvaluateDao) UpdateState(ctx context.Context, orgId, evaluateId string, state uint32, updateUserId string, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": evaluateId, "orgId": orgId}, bson.M{
		"$set": bson.M{
			"evaluateState": state,
			"updateUserId":  updateUserId,
			"updateTime":    updateTime,
		},
	})
	return err
}
